<?php
/**
 *	FILENAME: 		/libraries/ldap.php
 *	DESCRIPTION:	This library contains functions used to interact with Villanova University's LDAP server.
 *	AUTHOR:			Casey Burkhardt
 *	VERSION:		1.0.0
 *	LAST MODIFIED:	12/31/2009
 **/

global $LDAP_HOSTNAME;
$LDAP_HOSTNAME = "ldap.villanova.edu";

/**
 *	DESCRIPTION:	Checks if the provided LDAP username and password is valid for a Villanova student, faculty member, or staff member
 **/
function authenticateLDAPUser($username, $password) {
    global $LDAP_HOSTNAME;

    // First construct all of the RDN values for each bind attempt.
    // Students
    $rdn1 = "uid=" . $username . ", ou=" . strtoupper(substr($username, 0, 1)) . ", ou=Students, o=villanova.edu";
    $rdn2 = "uid=" . $username . ", ou=People, o=villanova.edu";
    // Faculty
    $rdn3 = "uid=" . $username . ", ou=Faculty, ou=Employees, o=villanova.edu";
    // Staff
    $rdn4 = "uid=" . $username . ", ou=Staff, ou=Employees, o=villanova.edu";

    $ldapConnection = ldap_connect($LDAP_HOSTNAME);
    if ($ldapConnection) {
        $bind1 = @ldap_bind($ldapConnection, $rdn1, $password);
        $bind2 = @ldap_bind($ldapConnection, $rdn2, $password);
        $bind3 = @ldap_bind($ldapConnection, $rdn3, $password);
        $bind4 = @ldap_bind($ldapConnection, $rdn4, $password);

        // Authenticate if any of the bind attempts worked.
        if ($bind1 || $bind2 || $bind3 || $bind4) {
            return TRUE;
        } else {
            return FALSE;
        }
        ldap_close($ldapConnection);
    } else {
        return FALSE;
    }
}

/**
 *	DESCRIPTION:	Checks to see if an LDAP record exists on the Villanova LDAP server.
 **/
function checkLDAPRecord($leadNodes, $target_node) {
    global $LDAP_HOSTNAME;

    // Connect and Bind anonymously to the Villanova LDAP server.
    $ldapConnection = ldap_connect($LDAP_HOSTNAME);
    if ($ldapConnection) {
        $bind = @ldap_bind($ldapConnection);
        $result = @ldap_search($ldapConnection, $leadNodes, $target_node);
        if (ldap_count_entries($ldapConnection, $result) > 0) {
            return TRUE;
        } else {
            return FALSE;
        }
    } else {
        return FALSE;
    }
}

/**
 *	DESCRIPTION:	Determines the record type based on a given UID value by checking against the structure of the LDAP server tree.
 **/
function ldap_record_type($userID) {
    global $LDAP_HOSTNAME;

    // Connect and Bind anonymously to the Villanova LDAP server.
    $ldapConnection = ldap_connect($LDAP_HOSTNAME);
    if ($ldapConnection) {
        $bind = @ldap_bind($ldapConnection);
        if (ldap_count_entries($ldapConnection, @ldap_search($ldapConnection, "ou=" . strtoupper(substr($userID, 0, 1)) . ", ou=Students, o=villanova.edu", "uid=" . $userID)) > 0) {
            return "Student";
        } elseif (ldap_count_entries($ldapConnection, @ldap_search($ldapConnection, "ou=People, o=villanova.edu", "uid=" . $userID)) > 0) {
            return "Student";
        } elseif (ldap_count_entries($ldapConnection, @ldap_search($ldapConnection, "ou=Faculty, ou=Employees, o=villanova.edu", "uid=" . $userID)) > 0) {
            return "Faculty";
        } elseif (ldap_count_entries($ldapConnection, @ldap_search($ldapConnection, "ou=Staff, ou=Employees, o=villanova.edu", "uid=" . $userID)) > 0) {
            return "Staff";
        } else {
            return FALSE;
        }
    } else {
        return FALSE;
    }
}

/**
 *	DESCRIPTION:	Returns all fields of an LDAP record given the record's lead nodes and the user ID.
 **/
function ldap_record($leadNodes, $userID) {
    global $LDAP_HOSTNAME;

    // Connect and Bind anonymously to the Villanova LDAP server.
    $ldapConnection = ldap_connect($LDAP_HOSTNAME);
    if ($ldapConnection) {
        $bind = @ldap_bind($ldapConnection);
        if (ldap_count_entries($ldapConnection, @ldap_search($ldapConnection, $leadNodes, "uid=" . $userID)) > 0) {
            $result = ldap_search($ldapConnection, $leadNodes, "uid=" . $userID);
            $record = ldap_get_entries($ldapConnection, $result);
            return $record;
        } else {
            return FALSE;
        }
    } else {
        return FALSE;
    }
}

/**
 *	DESCRIPTION:	Returns several LDAP record fields for each LDAP record found given a search string.
 **/
function ldapSearch($searchQuery) {
    global $LDAP_HOSTNAME;

    $ldapConnection = ldap_connect($LDAP_HOSTNAME);
    if ($ldapConnection) {
        // Search the four root dn's in parallel.
        $dnValues[] = "ou=People, o=villanova.edu";
        $dnValues[] = "ou=Students, o=villanova.edu";
        $dnValues[] = "ou=Faculty, ou=Employees, o=villanova.edu";
        $dnValues[] = "ou=Staff, ou=Employees, o=villanova.edu";

        foreach ($dnValues as $i) {
            // Every dn needs an associated connection resource.
            $connections[] = $ldapConnection;
        }

        // We'll search for any username, last name, first name, or full name that contains the search query.
        $searchString = "(|(uid=$searchQuery*)(sn=$searchQuery*)(givenname=$searchQuery*)(cn=$searchQuery*))";

        // Return only the userID, full name, and organizaitonal unit of the resulting entries.
        $resultLimiters = array("uid", "cn", "ou");
        $searchResults = ldap_search($connections, $dnValues, $searchString, $resultLimiters);

        $results = array();
        $resultCount = 0;

        // Iterate over each search result from each dn, and aggregate the results.
        foreach ($searchResults as $value) {
            if(ldap_count_entries($ldapConnection, $value) > 0) {
                $info = ldap_get_entries($ldapConnection, $value);
                $count = $count + $info["count"];
                $results = array_merge($results, $info);
            }
        }

        // Update the final result count and return results.
        $results["count"] = $count;
        return $results;
    } else {
        return FALSE;
    }
}
?>